home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / archiver / pdtar.zip / TAR.C < prev    next >
C/C++ Source or Header  |  1988-05-15  |  20KB  |  807 lines

  1. /*
  2.  * A public domain tar(1) program.
  3.  * 
  4.  * Written by John Gilmore, ihnp4!hoptoad!gnu, starting 25 Aug 85.
  5.  * MS-DOS port 2/87 by Eric Roskos.
  6.  * Minix  port 3/88 by Eric Roskos.
  7.  *
  8.  * @(#)tar.c 1.21 10/29/86 Public Domain - gnu
  9.  */
  10.  
  11. #include <stdio.h>
  12. #include <sys/types.h>            /* Needed for typedefs in tar.h */
  13.  
  14. #ifdef MSDOS
  15. #include <conio.h>
  16. #include <fcntl.h>
  17. #endif
  18. #ifdef V7
  19. FILE *fopen();
  20. char *fgets();
  21. #endif
  22.  
  23. extern char    *malloc();
  24. extern char    *
  25. strncpy(), *index(), *rindex();
  26. extern char    *optarg;            /* Pointer to argument */
  27. extern int      optind;            /* Global argv index from getopt */
  28.  
  29. /*
  30.  * The following causes "tar.h" to produce definitions of all the
  31.  * global variables, rather than just "extern" declarations of them.
  32.  */
  33. #define TAR_EXTERN                /**/
  34. #include "tar.h"
  35.  
  36. /*
  37.  * We should use a conversion routine that does reasonable error
  38.  * checking -- atoi doesn't.  For now, punt.  FIXME.
  39.  */
  40. #define intconv    atoi
  41. extern int      getoldopt();
  42. extern void     read_and();
  43. extern void     list_archive();
  44. extern void     extract_archive();
  45. extern void     create_archive();
  46.  
  47. static FILE    *namef;            /* File to read names from */
  48. static char   **n_argv;            /* Argv used by name routines */
  49. static int      n_argc;            /* Argc used by name routines */
  50.  
  51.  /* They also use "optind" from getopt(). */
  52.  
  53. static char    *sccsid =
  54. "@(#)tar.c 1.21 10/29/86 Public Domain - gnu - Minix port 3/05/88 Eric Roskos (csed-1!roskos)";
  55.  
  56. #ifdef MSDOS
  57. /*
  58.  * see convmode, below.  This list is the list of files that should be
  59.  * opened with mode O_BINARY to prevent CR/LF conversions while they
  60.  * are being read in.  FIXME: it is my intent to eventually add an
  61.  * option to the command line that lets you add arbitrarily many new
  62.  * extensions to this list, so people won't have problems with the
  63.  * list being inadequate for them.  I wish there was an easier way, but
  64.  * this one is fairly consistent if you think about it.
  65.  */
  66. #define NBINEXTS    20
  67.  
  68. static char    *binexts[NBINEXTS] =        /* extensions for O_BINARY files */
  69. {
  70.     "com",
  71.     "exe",
  72.     "obj",
  73.     0                            /* required */
  74. };
  75.  
  76. #endif
  77.  
  78. void            describe();
  79.  
  80.  
  81. /*
  82.  * Main routine for tar.
  83.  */
  84. main(argc, argv)
  85. int             argc;
  86. char          **argv;
  87. {
  88.  
  89.     /*
  90.      * Uncomment this message in particularly buggy versions...
  91.      * fprintf(stderr, "tar: You are running an experimental PD tar, maybe
  92.      * use /bin/tar.\n"); 
  93.      */
  94.  
  95.     tar = "tar";                /* Set program name */
  96. #ifdef MSDOS
  97.     physdrv = 0;                /* set default drive */
  98.     devsize = 720;                /* default drive size */
  99.     ftty = open("CON", O_RDWR);        /* open console */
  100. #else /* !MSDOS */
  101.     ftty = open("/dev/tty", 2);
  102. #endif /* !MSDOS */
  103.     if (ftty < 0)
  104.     {
  105.         fprintf(stderr, "Can't open %s for I/O\n",
  106. #ifdef MSDOS
  107.         "console"
  108. #else
  109.         "/dev/tty"
  110. #endif
  111.             );
  112.         exit(EX_SYSTEM);
  113.     }
  114.  
  115.     options(argc, argv);
  116.  
  117.     name_init(argc, argv);
  118.  
  119. #ifdef MSDOS
  120.     if (f_phys)
  121.     {
  122.         uprintf(ftty,"tar: archive on %dK drive %c\n",
  123.             devsize/2, 'A' +  physdrv);
  124.         uprintf(ftty,"tar: insert %s disk in drive '%c' and press [Enter]: ",
  125.             f_create? "formatted" : "first",
  126.             'A' + physdrv);
  127.         while (ugetc(ftty)!='\n') ;
  128.     }
  129. #endif
  130.  
  131.     if (f_create)
  132.     {
  133.         if (f_extract || f_list)
  134.             goto dupflags;
  135.         create_archive();
  136.     }
  137.     else
  138.     if (f_extract)
  139.     {
  140.         if (f_list)
  141.             goto dupflags;
  142.         read_and(extract_archive);
  143.     }
  144.     else
  145.     if (f_list)
  146.     {
  147.         read_and(list_archive);
  148.     }
  149.     else
  150.     {
  151. dupflags:
  152.         fprintf(stderr,
  153.             "tar: you must specify exactly one of the c, t, or x options\n");
  154.         describe();
  155.         exit(EX_ARGSBAD);
  156.     }
  157.     putchar('\n');
  158.     fflush(stdout);
  159. #ifndef MSDOS
  160.     sync(); /* insure all floppy buffers are written out */
  161. #endif
  162.     exit(0);
  163. }
  164.  
  165.  
  166. /*
  167.  * Parse the options for tar.
  168.  */
  169. int
  170. options(argc, argv)
  171. int             argc;
  172. char          **argv;
  173. {
  174.     register int    c;            /* Option letter */
  175.     void            addbinext();
  176.  
  177.     /* Set default option values */
  178.     blocking = DEFBLOCKING;        /* From Makefile */
  179.     ar_file = DEF_AR_FILE;        /* From Makefile */
  180.  
  181.     /* Parse options */
  182.     while ((c = getoldopt(argc, argv, "b:BcdDf:hikmopsS:tT:u:vV:xzZ")
  183.         ) != EOF)
  184.     {
  185.         switch (c)
  186.         {
  187.  
  188.         case 'b':
  189.             blocking = intconv(optarg);
  190.             break;
  191.  
  192.         case 'B':
  193.             f_reblock++;        /* For reading 4.2BSD pipes */
  194.             break;
  195.  
  196.         case 'c':
  197.             f_create++;
  198.             break;
  199.  
  200.         case 'd':
  201.             f_debug++;            /* Debugging code */
  202.             break;                /* Yes, even with dbx */
  203.  
  204.         case 'D':
  205.             f_sayblock++;        /* Print block #s for debug */
  206.             break;                /* of bad tar archives */
  207.  
  208.         case 'f':
  209.             ar_file = optarg;
  210.             break;
  211.  
  212.         case 'h':
  213.             f_follow_links++;    /* follow symbolic links */
  214.             break;
  215.  
  216.         case 'i':
  217.             f_ignorez++;        /* Ignore zero records (eofs) */
  218.  
  219.             /*
  220.              * This can't be the default, because Unix tar writes two records
  221.              * of zeros, then pads out the block with garbage. 
  222.              */
  223.             break;
  224.  
  225.         case 'k':                /* Don't overwrite files */
  226.             f_keep++;
  227.             break;
  228.  
  229.         case 'm':
  230.             f_modified++;
  231.             break;
  232.  
  233.         case 'o':                /* Generate old archive */
  234.             f_oldarch++;
  235.             break;
  236.  
  237.         case 'p':
  238.             f_use_protection++;
  239.             (void) umask(0);    /* Turn off kernel "help" */
  240.             break;
  241.  
  242.         case 's':
  243.             f_sorted_names++;    /* Names to extr are sorted */
  244.             break;
  245. #ifdef MSDOS
  246.         case 'S':
  247.             devsize = atoi(optarg); /* size of DOS disk drive */
  248.             devsize <<= 1;        /* convert K to blocks */
  249.             break;
  250. #endif
  251.         case 't':
  252.             f_list++;
  253.             break;
  254.  
  255.         case 'T':
  256.             name_file = optarg;
  257.             f_namefile++;
  258.             break;
  259. #ifdef MSDOS
  260.         case 'u':
  261.             addbinext(optarg);
  262.             break;
  263. #endif
  264.         case 'v':
  265.             f_verbose++;
  266.             break;
  267. #ifdef MSDOS
  268.         case 'V':
  269.             f_phys++;
  270.             physdrv = toupper(*optarg) - 'A';
  271.             if (physdrv > 4 || physdrv < 0)
  272.             {
  273.                 fprintf(stderr, "tar: drive letter for -V must be A-D\n");
  274.                 exit(EX_ARGSBAD);
  275.             }
  276.             break;                
  277. #endif /* MSDOS */
  278.  
  279.         case 'x':
  280.             f_extract++;
  281.             break;
  282.  
  283.         case 'z':                /* Easy to type */
  284.         case 'Z':                /* Like the filename extension .Z */
  285. #ifndef MSDOS
  286.             f_compress++;
  287. #else
  288.             fprintf(stderr, "Running compress as a subprocess is not supported under DOS.\n");
  289.             fprintf(stderr, "Run compress separately instead, for same effect.\n");
  290. #endif
  291.             break;
  292.  
  293.         default:
  294.         case '?':
  295.             describe();
  296.             exit(EX_ARGSBAD);
  297.  
  298.         }
  299.     }
  300.  
  301.     blocksize = blocking * RECORDSIZE;
  302. }
  303.  
  304.  
  305. /* FIXME, describe tar options here */
  306. void
  307. describe()
  308. {
  309.  
  310.     fputs("tar: valid options:\n\
  311. -b N    blocking factor N (block size = Nx512 bytes)\n\
  312. -B    reblock as we read (for reading 4.2BSD pipes)\n\
  313. -c    create an archive\n\
  314. -D    dump record number within archive with each message\n\
  315. -f F    read/write archive from file or device F\n", stderr);
  316.     fputs("-h    don't dump symbolic links; dump the files they point to\n\
  317. -i    ignore blocks of zeros in the archive, which normally mean EOF\n\
  318. -k    keep existing files, don't overwrite them from the archive\n\
  319. -m    don't extract file modified time\n\
  320. -o    write an old V7 format archive, rather than ANSI [draft 6] format\n\
  321. -p    do extract all protection information\n", stderr);
  322. #ifdef MSDOS
  323.     fputs("-S X    device for -V option is X Kbyte drive\n", stderr);
  324. #endif
  325.     fputs("-s    list of names to extract is sorted to match the archive\n\
  326. -t    list a table of contents of an archive\n\
  327. -T F    get names to extract or create from file F\n", stderr);
  328. #ifdef MSDOS
  329.     fputs("\
  330. -u X    add X to list of file extensions to be opened in BINARY mode\n\
  331.     (use '.' to denote 'files with no extension')\n\
  332. -V X    use drive X (X=A..D) in multivolume mode; ignore -f if present\n",
  333.         stderr);
  334. #endif
  335.     fputs("\
  336. -v    verbosely list what files we process\n\
  337. -x    extract files from an archive\n", stderr);
  338. #ifndef MSDOS
  339.  
  340.     /*
  341.      * regrettably, DOS doesn't have real pipes, just artificial shell-level
  342.      * ones.  It is better to just use those. 
  343.      */
  344.     fputs("\
  345. -z or Z    run the archive through compress(1)\n", stderr);
  346. #endif
  347. }
  348.  
  349.  
  350. /*
  351.  * Set up to gather file names for tar.
  352.  *
  353.  * They can either come from stdin or from argv.
  354.  */
  355. name_init(argc, argv)
  356. int             argc;
  357. char          **argv;
  358. {
  359.  
  360.     if (f_namefile)
  361.     {
  362.         if (optind < argc)
  363.         {
  364.             fprintf